home *** CD-ROM | disk | FTP | other *** search
/ ftp.qualcomm.com / 2014.06.ftp.qualcomm.com.tar / ftp.qualcomm.com / eudora / developers / emsapi / carbon_emsapi.sit.hqx / Macintosh API Support / emsdrive.c < prev    next >
C/C++ Source or Header  |  2001-03-08  |  36KB  |  1,384 lines

  1. /* ======================================================================
  2.  
  3.     Test driver for Eudora EMSAPI version v3
  4.  
  5.     Filename:            emsdrive.c
  6.     Last Edited:        March 7, 1997
  7.     Authors:            Laurence Lundblade, Scott Gruby,
  8.                         Myra Callen, Bob Fronabarger
  9.     Copyright:            1995, 1996 QUALCOMM Inc.
  10.     Technical support:    <emsapi-info@qualcomm.com>
  11. */
  12.  
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <Icons.h>
  16.  
  17. #include "emsapi-mac.h"
  18. #include "copycat.h"
  19. #include "mimetype.h"
  20. #include "usertrans.h"
  21.  
  22.  
  23. void WriteZero(void *pointer,long size);
  24.  
  25. #define Zero(x) WriteZero(&(x),sizeof(x))
  26. #define SetSize(x)    (x).size = sizeof(x)
  27.  
  28. void WriteZero(void *pointer,long size)
  29. {
  30.     Byte *u = (Byte*) pointer;
  31.     
  32.     while (size--)
  33.         *u++ = '\0';
  34. }
  35.  
  36. /*****************************************************************/
  37. /*  G L O B A L S  and  C O N S T A N T S
  38. /*****************************************************************/
  39.  
  40. #define kBaseResID            128
  41. #define kErrorALRTid        300
  42. #define kNoteALRTid            310
  43. #define kAboutALRTid        400
  44.  
  45. #define mApple                1501
  46. #define iAbout                1
  47. #define iAboutPlugins        2
  48.  
  49. #define mFile                1502
  50. #define iQuit                17
  51.  
  52. #define mEdit                1503
  53. #define mTranslators        220
  54.  
  55. #define mMailbox            1504
  56.  
  57. #define mMessage            1505
  58. #define mAttach                222
  59.  
  60. #define mTransfer            1506
  61.  
  62. #define mSpecial            1507
  63. #define mSettings            223
  64.  
  65. #define mWindow                1514
  66.  
  67. #define    kHeaderOffset        48
  68. #define kDummyHOffset        233
  69. #define kTransHeightOffset     60
  70. #define kNumberofButtons    2
  71. #define kTransTopOffset        4
  72. #define kSecondButtonOffset    30
  73. #define kButHeight            18
  74. #define kTransButWidth        120
  75. #define kTestButWidth        96
  76. #define    kIconHOffset        4
  77. #define kButHOffset            42
  78. #define    kTextHOffset        168
  79. #define kWindowWidth        528
  80.  
  81. #define kOK                    1
  82. #define kCancel                2
  83. #define kFactorySettings    3
  84.  
  85. #define kProgressDlogID        500
  86. #define kMimeDlogID            600
  87. #define kAddressDlogID        700
  88.  
  89. #define kDefModuleIcon        10128
  90. #define kDefTransIcon        10129
  91.  
  92. Boolean gDone = false;
  93.  
  94. unsigned char *translatorErrors[] = {
  95.     "\pEMSR_OK",
  96.     "\pEMSR_UNKNOWN_FAIL",
  97.     "\pEMSR_CANT_TRANS",
  98.     "\pEMSR_INVALID_TRANS",
  99.     "\pEMSR_NO_ENTRY",
  100.     "\pEMSR_NO_INPUT_FILE",
  101.     "\pEMSR_CANT_CREATE",
  102.     "\pEMSR_TRANS_FAILED",
  103.     "\pEMSR_INVALID",
  104.     "\pEMSR_NOT_NOW",
  105.     "\pEMSR_NOW", 
  106.     "\pEMSR_ABORTED",
  107.     "\pEMSR_DATA_UNCHANGED"
  108. };
  109.  
  110. /* Keep track of translatorButtons on translator modules window */
  111. typedef struct TranslatorButtons {
  112.     emsTranslator            trans;
  113.     ControlHandle            ctlH1, ctlH2;
  114.     void                    (*proc1)(emsTranslator*);
  115.     void                    (*proc2)(emsTranslator*);
  116. } TranslatorButtons;
  117.  
  118. /* Module Info from init call */
  119. static short                gModuleID, gOurResRefNum, gSpecialMenuLen;
  120. static long                    gContext;
  121. static Handle                gModuleGlobalsH;
  122. static ControlHandle        gMimeButH, gAddressButH, gContextPop;
  123. static emsMIMEtype          **gMimeTypeH;
  124. static StringHandle          **gAddressesH;
  125. static WindowPtr            gDebugWindow = nil;
  126.  
  127. static emsPluginInfo        gPluginInfo;
  128. static emsMailConfig        gMailConfig;
  129. static TranslatorButtons   *gTranslBtns;
  130. static EMSProgressUPP        gProgressUPP;
  131. static DialogPtr            gProgressDlg;
  132. static emsResultStatus        gResultStatus;
  133.  
  134. /*****************************************************************/
  135. /*  P R O T O T Y P E S
  136. /*****************************************************************/
  137.  
  138. void      main();
  139. void      ToolboxInit();
  140. void    MenuBarInit();
  141. void     DoInitialize();
  142. void    CleanUp();
  143.  
  144. void    EventLoop();
  145. void    DoEvent(EventRecord *eventPtr);
  146. void    HandleMouseDown(EventRecord *eventPtr);
  147. void    HandleMenuChoice(long menuChoice);
  148. void     DoUpdate(WindowPtr theWindow);
  149.  
  150. void    DrawWindow(WindowPtr window);
  151. void    DoTranslation(emsTranslator *trans);
  152. void    CanTranslation(emsTranslator *trans);
  153. void    NoTranslation(emsTranslator *trans);
  154.  
  155. void    DoMimeDlog();
  156. void    RestoreMimeDefaults(DialogPtr theDialog);
  157. void    SaveMimeSettingsToFile(DialogPtr theDialog);
  158. void    BuildNewMimeData();
  159.  
  160. void    DoAddressDlog();
  161. void    RestoreAddressDefaults(DialogPtr theDialog);
  162. void    SaveAddressSettingsToFile(DialogPtr theDialog);
  163. void    SetupAddressDialog(DialogPtr theDialog);
  164. void    GetAddressChanges(DialogPtr theDialog);
  165. void    InitAddressData();
  166.  
  167. short    ContextToMenuItem(long context);
  168. long    MenuItemToContext(short item);
  169.  
  170. void    DoMessage(long status);
  171. void    DoError(long error, Str63 message);
  172. void    GetStringHdl(short id, Str255 theStr);
  173. void     SetWindowFont(DialogPtr theDialog, short fontNum, short fontSize, Style fontStyle);
  174. short    ProgressProc(emsProgressData *prog);
  175.  
  176.  
  177. /*****************************************************************/
  178. /*  M A I N  P R O G R A M
  179. /*****************************************************************/
  180.  
  181. /* ----------------------------------------------------------------------
  182.     Application entry
  183.  */
  184. void main(void)
  185. {
  186.     ToolboxInit();
  187.     MenuBarInit();
  188.     DoInitialize();
  189.     EventLoop();
  190.     CleanUp();
  191. }
  192.  
  193.  
  194. /* ----------------------------------------------------------------------
  195.     Standard toolbox initialization
  196.  */
  197. void ToolboxInit()
  198. {
  199.     MaxApplZone();
  200.     InitGraf(&qd.thePort);
  201.     InitFonts();
  202.     InitWindows();
  203.     InitMenus();
  204.     TEInit();
  205.     InitDialogs(0L);
  206.     FlushEvents(everyEvent, 0);
  207.     InitCursor();
  208. }
  209.  
  210.  
  211. /* ----------------------------------------------------------------------
  212.     Setup menu bar
  213.  */
  214. void MenuBarInit(void)
  215. {
  216.     Handle            menuBar;
  217.     MenuHandle        menu;
  218.     
  219.     menuBar = GetNewMBar(kBaseResID);
  220.     SetMenuBar(menuBar);
  221.     menu = GetMenuHandle(mApple);
  222.     AppendResMenu(menu, 'DRVR');
  223.     DrawMenuBar();
  224. }
  225.  
  226.  
  227. /* ----------------------------------------------------------------------
  228.     Put up window with module/translator info
  229.  */
  230. void DoInitialize(void)
  231. {
  232.     Rect            r;
  233.     short            i, v, api_version;
  234.     long            theResult;
  235.     OSErr            err;
  236.     MenuHandle        translMenu = nil, attachMenu, specialMenu;
  237.     Str255 message;
  238.     
  239.     /* get our resource ref num */
  240.     gOurResRefNum = CurResFile();
  241.  
  242.     /* Pretend we're like the component manager, handle the globals storage */
  243.     gModuleGlobalsH = NewHandle(sizeof(emsUserGlobals));
  244.     
  245.     SetSize(gMailConfig);
  246.     gMailConfig.configDir.vRefNum = -1;
  247.     gMailConfig.configDir.parID = 1;
  248.     gMailConfig.configDir.name[0] = '\0';
  249.     gMailConfig.userAddr.size = sizeof(emsAddress);
  250.     // etc...
  251.     
  252.     Zero(gPluginInfo);
  253.     SetSize(gPluginInfo);
  254.     
  255.     Zero(gResultStatus);
  256.     SetSize(gResultStatus);
  257.     
  258.     /* create callback function pointer for progress function */
  259.     gProgressUPP = NewEMSProgressProc(ProgressProc);
  260.     
  261.     /* Get this plugin's version. */
  262.     theResult = ems_plugin_version(gModuleGlobalsH, &api_version);
  263.     if (theResult != EMSR_OK)
  264.         api_version = -1;
  265.  
  266.     /* Initialize this module and get the module information. */
  267.     theResult = ems_plugin_init(gModuleGlobalsH, EMS_VERSION, &gMailConfig, &gPluginInfo);
  268.     DoError(theResult, "\pplugin_init failed");
  269.     if (gPluginInfo.icon == nil) // Substitute our dummy icon if plugin doesn't have one
  270.         err = GetIconSuite(&gPluginInfo.icon, kDefModuleIcon, svAllAvailableData);
  271.  
  272.     if (gPluginInfo.numTrans > 0) {
  273.         translMenu = NewMenu(mTranslators, "\pTranslators");
  274.         InsertMenu(translMenu, hierMenu);
  275.     }
  276.     
  277.     attachMenu = NewMenu(mAttach, "\pAttach");
  278.     if (gPluginInfo.numAttachers == 0)
  279.         AppendMenu(attachMenu, "\p(None installed");
  280.     InsertMenu(attachMenu, hierMenu);
  281.     
  282. #if EMS_HAS_PLUGIN_CONFIG
  283.     {
  284.     MenuHandle        settingsMenu;
  285.     
  286.     settingsMenu = NewMenu(mSettings, "\pSettings");
  287.     AppendMenu(settingsMenu, "\pX");
  288.     CopyPP(*gPluginInfo.desc, message);
  289.     CatPP("\p...", message);
  290.     SetMenuItemText(settingsMenu, 1, message);
  291.     InsertMenu(settingsMenu, hierMenu);
  292.     }
  293. #endif
  294.     if (gPluginInfo.numSpecials > 0) {
  295.         specialMenu = GetMenu(mSpecial);
  296.         AppendMenu(specialMenu, "\p(-");
  297.         gSpecialMenuLen = CountMItems(specialMenu);
  298.     }
  299.     
  300.     BuildNewMimeData();
  301.     InitAddressData();
  302.     gContext = EMSF_Q4_TRANSMISSION;    // EMSF_ON_REQUEST;
  303.     
  304.     v = gPluginInfo.numTrans * kTransHeightOffset + kHeaderOffset;
  305.     SetRect(&r, 10, 50, 10 + kWindowWidth, 50 + v);
  306.     gDebugWindow = NewCWindow(nil, &r, "\pTranslator Debugger", false, 0, (WindowPtr) -1L, false, 0);
  307.     SetPort(gDebugWindow);
  308.     
  309.     /* Buttons for dummy testing information */
  310.     SetRect(&r, kWindowWidth - kTestButWidth - 16, 4, kWindowWidth - 16, 4 + kButHeight);
  311.     gAddressButH = NewControl(gDebugWindow, &r, "\pAddress", true, 0, 0, 1, pushButProc, 0);
  312.     OffsetRect(&r, 0, kButHeight + 4);
  313.     gMimeButH = NewControl(gDebugWindow, &r, "\pMime Type", true, 0, 0, 1, pushButProc, 0);
  314.     SetRect(&r, kDummyHOffset - 5, 27, kDummyHOffset + 180 - 5, 27 + 16);
  315.     i = ContextToMenuItem(gContext);
  316.     gContextPop = NewControl(gDebugWindow, &r, "\pContext:", true, i, 2020, 48, 1018, 0);
  317.     SetControlValue(gContextPop, i);
  318.  
  319. #if EMS_HAS_TRANSLATOR_INFO
  320.     // create two buttons for every translator, save the handle in the array
  321.     gTranslBtns = (TranslatorButtons*) NewPtr(sizeof(TranslatorButtons) * gPluginInfo.numTrans);
  322.     for (i = 0; i < gPluginInfo.numTrans; i++) {
  323.         TranslatorButtons    translBtn;
  324.  
  325.         translBtn.trans.size = sizeof(emsTranslator);
  326.         translBtn.trans.id = i + 1;
  327.         translBtn.trans.type = 0;
  328.         translBtn.trans.flags = 0;
  329.         translBtn.trans.desc = nil;
  330.         translBtn.trans.icon = nil;
  331.         translBtn.trans.properties = nil;
  332.         theResult = ems_translator_info(gModuleGlobalsH, &translBtn.trans);
  333.         if (theResult == EMSR_OK) {
  334.             v = (i * kTransHeightOffset) + kHeaderOffset + kTransTopOffset;
  335.             SetRect(&r, kButHOffset, v, kButHOffset + kTransButWidth, v + kButHeight);
  336.             translBtn.ctlH1 = NewControl(gDebugWindow, &r, "\pCan Trans File", true, 0, 0, 1, pushButProc, 0);
  337.             
  338.             OffsetRect(&r, 0, kSecondButtonOffset - kTransTopOffset);    // 26
  339.             translBtn.ctlH2 = NewControl(gDebugWindow, &r, "\pTranslate File", true, 0, 0, 1, pushButProc, 0);
  340.  
  341. #if EMS_HAS_CAN_TRANSLATE
  342.             translBtn.proc1 = CanTranslation;
  343. #else
  344.             translBtn.proc1 = NoTranslation;
  345. #endif
  346. #if EMS_HAS_TRANSLATE_FILE
  347.             translBtn.proc2 = DoTranslation;
  348. #else
  349.             translBtn.proc2 = NoTranslation;
  350. #endif
  351.             gTranslBtns[i] = translBtn;
  352.             
  353.             if (translBtn.trans.desc != nil) {
  354.                 AppendMenu(translMenu, "\pX");
  355.                 CopyPP(*translBtn.trans.desc, message);
  356.                 SetMenuItemText(translMenu, CountMItems(translMenu), message);
  357.             }
  358.         }
  359.     }
  360. #endif
  361. #if EMS_HAS_ATTACHER_INFO
  362.     for (i = 0; i < gPluginInfo.numAttachers; i++) {
  363.         emsMenu        menuRec;
  364.         
  365.         SetSize(menuRec);
  366.         menuRec.id = i;
  367.         menuRec.desc = nil;
  368.         theResult = ems_attacher_info(gModuleGlobalsH, &menuRec);
  369.         AppendMenu(attachMenu, "\pX");
  370.         if (theResult == EMSR_OK && menuRec.desc != nil) {
  371.             CopyPP(*menuRec.desc, message);
  372.             DisposeHandle((Handle) menuRec.desc);
  373.         }
  374.         else
  375.             CopyPP("\pError", message);
  376.         SetMenuItemText(attachMenu, CountMItems(attachMenu), message);
  377.     }
  378. #endif
  379. #if EMS_HAS_SPECIAL_INFO
  380.     for (i = 0; i < gPluginInfo.numSpecials; i++) {
  381.         emsMenu        menuRec;
  382.         
  383.         SetSize(menuRec);
  384.         menuRec.id = i;
  385.         menuRec.desc = nil;
  386.         theResult = ems_special_info(gModuleGlobalsH, &menuRec);
  387.         AppendMenu(specialMenu, "\pX");
  388.         if (theResult == EMSR_OK && menuRec.desc != nil) {
  389.             CopyPP(*menuRec.desc, message);
  390.             DisposeHandle((Handle) menuRec.desc);
  391.         }
  392.         else
  393.             CopyPP("\pError", message);
  394.         SetMenuItemText(specialMenu, CountMItems(specialMenu), message);
  395.     }
  396. #endif
  397.     ShowWindow(gDebugWindow);
  398. }
  399.  
  400.  
  401. /* ----------------------------------------------------------------------
  402.     Clean up globals before quit
  403. */
  404. void CleanUp(void) 
  405. {
  406.     TranslatorButtons    translator;
  407.     short                i;
  408.     
  409.     if (gModuleGlobalsH != nil) {
  410.         ems_plugin_finish(gModuleGlobalsH);
  411.         DisposeHandle(gModuleGlobalsH);
  412.         gModuleGlobalsH = nil;
  413.     }
  414.     if (gTranslBtns != nil) {
  415.         for (i = 0; i < gPluginInfo.numTrans; i++) {
  416.             translator = gTranslBtns[i];
  417.             if (translator.trans.desc != nil)
  418.                 DisposeHandle((Handle) translator.trans.desc);
  419.             if (translator.trans.icon != nil)
  420.                 DisposeIconSuite(translator.trans.icon, true);
  421.         }
  422.         DisposePtr((Ptr) gTranslBtns);
  423.     }
  424.     DisposeRoutineDescriptor(gProgressUPP);
  425. }
  426.  
  427. #pragma mark -
  428. /*****************************************************************/
  429. /*  E V E N T  H A N D L I N G
  430. /*****************************************************************/
  431. \
  432. /* ----------------------------------------------------------------------
  433.     Do event loop
  434.  */
  435. void EventLoop(void)
  436. {        
  437.     EventRecord        event;
  438.     
  439.     while (!gDone) {
  440.         WaitNextEvent(everyEvent, &event, 30, nil);
  441.         DoEvent(&event);
  442.     }
  443. }
  444.  
  445.  
  446. /* ----------------------------------------------------------------------
  447.     Handle event
  448.  */
  449. void DoEvent(EventRecord *theEvent)
  450. {
  451.     char        theChar;
  452.     
  453.     switch (theEvent->what) {
  454.         case mouseDown:
  455.             HandleMouseDown(theEvent);
  456.             break;
  457.         case keyDown:
  458.         case autoKey:
  459.             theChar = theEvent->message & charCodeMask;
  460.             if (theEvent->modifiers & cmdKey)
  461.                 HandleMenuChoice(MenuKey(theChar));
  462.             break;
  463.         case updateEvt:
  464.             DoUpdate((WindowPtr) theEvent->message);
  465.             break;
  466.     }
  467. }
  468.  
  469.  
  470. /* ----------------------------------------------------------------------
  471.     Handle mouse down events
  472.  */
  473. void HandleMouseDown(EventRecord *eventPtr)
  474. {
  475.     WindowPtr            window;
  476.     Point                mousePt;
  477.     short                i, thePart, part;
  478.     ControlHandle       whichControl;
  479.     ControlActionUPP    actionUPP;
  480.     TranslatorButtons    translBtn;
  481.     
  482.     thePart = FindWindow(eventPtr->where, &window);
  483.     switch (thePart) {
  484.         case inMenuBar:
  485.             HandleMenuChoice(MenuSelect(eventPtr->where));
  486.             HiliteMenu(0);
  487.             break;
  488.         case inSysWindow:
  489.             SystemClick(eventPtr, window);
  490.             break;
  491.         case inContent:
  492.             if (window == gDebugWindow) {
  493.                 SelectWindow(window);
  494.                 mousePt = eventPtr->where;
  495.                 GlobalToLocal(&mousePt);
  496.                 whichControl = nil;
  497.                 part = FindControl(mousePt, window, &whichControl);
  498.                 if (whichControl == nil)
  499.                     break;
  500.                 actionUPP = (whichControl == gContextPop) ? (ControlActionUPP) -1 : nil;
  501.                 part = TrackControl(whichControl, mousePt, actionUPP);
  502.                 if (part == kControlButtonPart) {
  503.                     HiliteControl(whichControl, 255);
  504.                     if (whichControl == gAddressButH)
  505.                         DoAddressDlog();
  506.                     else if (whichControl == gMimeButH)
  507.                         DoMimeDlog();
  508.                     else if (whichControl == gContextPop) {
  509.                         part = TrackControl(gContextPop, mousePt, (ControlActionUPP) -1);
  510.                         if (part != 0) {
  511.                             part = GetControlValue(gContextPop);
  512.                             part++;
  513.                         }
  514.                     }
  515.                     else {
  516.                         for (i = 0; i < gPluginInfo.numTrans; i++) {
  517.                             translBtn = gTranslBtns[i];
  518.                             if (whichControl == translBtn.ctlH1) {
  519.                                 (*translBtn.proc1)(&translBtn.trans);
  520.                                 break;
  521.                             }
  522.                             else if (whichControl == translBtn.ctlH2) {
  523.                                 (*translBtn.proc2)(&translBtn.trans);
  524.                                 break;
  525.                             }
  526.                         }
  527.                     }
  528.                     HiliteControl(whichControl, 0);
  529.                 }
  530.                 else if (part == kControlLabelPart) {
  531.                     part = GetControlValue(gContextPop);
  532.                     gContext = MenuItemToContext(part);
  533.                 }
  534.             }
  535.             break;
  536.         case inDrag:
  537.             DragWindow(window, eventPtr->where, &qd.screenBits.bounds);
  538.             break;
  539.     }
  540. }
  541.  
  542.  
  543. /* ----------------------------------------------------------------------
  544.     Handle menu events
  545.  */
  546. void HandleMenuChoice(long menuChoice)
  547. {
  548.     short            menu, item;
  549.     MenuHandle        appleMenu;
  550.     Str255            theStr;
  551.     
  552.     if (menuChoice != 0) {
  553.         menu = HiWord(menuChoice);
  554.         item = LoWord(menuChoice);
  555.         switch (menu) {
  556.             case mApple:
  557.                 switch (item) {
  558.                     case iAbout:
  559.                         Alert(kAboutALRTid, nil);
  560.                         break;
  561.                     case iAboutPlugins:
  562.                         break;
  563.                     default:
  564.                         appleMenu = GetMenuHandle(mApple);
  565.                         GetMenuItemText(appleMenu, item, theStr);
  566.                         OpenDeskAcc(theStr);
  567.                 }
  568.                 break;
  569.             case mFile:
  570.                 if (item == iQuit)
  571.                     gDone = true;
  572.                 break;
  573. #if EMS_HAS_TRANSLATOR_INFO
  574.             case mTranslators:    // mEdit
  575.                 {
  576.                 TranslatorButtons    translBtn = gTranslBtns[item - 1];
  577.                 (*translBtn.proc2)(&translBtn.trans);    // Do Translation
  578.                 }
  579.                 break;
  580. #endif
  581. #if EMS_HAS_ATTACHER_HOOK
  582.             case mAttach:        // mMessage
  583.                 {
  584.                 emsMenu            menuRec;
  585.                 FSSpec            dir;
  586.                 emsDataFileH    attachH = nil;
  587.                 long            status, numAttach = 0;
  588.                 
  589.                 SetSize(menuRec);
  590.                 menuRec.id = item - 1;
  591.                 menuRec.desc = nil;
  592.                 Zero(dir);
  593.                 status = ems_attacher_hook(gModuleGlobalsH, &menuRec, &dir, &numAttach, &attachH);
  594.                 if (attachH != nil) {
  595.                     DisposeHandle((Handle) attachH);
  596.                     NumToString(numAttach, theStr);
  597.                     ParamText(theStr, "\p files attached", "\p", "\p");
  598.                     Alert(kNoteALRTid, nil);
  599.                 }
  600.                 DoError(status, "\pattacher_hook failed");
  601.                 }
  602.                 break;
  603. #endif
  604. #if EMS_HAS_SPECIAL_HOOK
  605.             case mSpecial:
  606.                 {
  607.                 emsMenu        menuRec;
  608.                 long        status;
  609.                 
  610.                 SetSize(menuRec);
  611.                 menuRec.id = item - gSpecialMenuLen - 1;
  612.                 menuRec.desc = nil;
  613.                 status = ems_special_hook(gModuleGlobalsH, &menuRec);
  614.                 DoError(status, "\pspecial_hook failed");
  615.                 }
  616.                 break;
  617. #endif
  618. #if EMS_HAS_PLUGIN_CONFIG
  619.             case mSettings:
  620.                 {
  621.                 long        status2;
  622.                 
  623.                 status2 = ems_plugin_config(gModuleGlobalsH, &gMailConfig);
  624.                 DoError(status2, "\pplugin_config failed");
  625.                 }
  626.                 break;
  627. #endif
  628.         }
  629.     }
  630. }
  631.  
  632.  
  633. /* ----------------------------------------------------------------------
  634.     Do window update
  635. */
  636. void DoUpdate(WindowPtr theWindow)
  637. {
  638.     GrafPtr        savePort;
  639.     
  640.     GetPort(&savePort);
  641.     SetPort(theWindow);
  642.     BeginUpdate(theWindow);
  643.     if (theWindow == gDebugWindow)
  644.         DrawWindow(theWindow);
  645.     EndUpdate(theWindow);
  646.     SetPort(savePort);
  647. }
  648.  
  649. #pragma mark -
  650.  
  651. /*****************************************************************/
  652. /*  T R A N S L A T O R S
  653. /*****************************************************************/
  654.  
  655. /* ----------------------------------------------------------------------
  656.     Display the translators in a particular module with translatorButtons for
  657.     invoking operatations
  658. */
  659. void DrawWindow(WindowPtr window)
  660. {
  661.     short           api_version;
  662. #if EMS_HAS_TRANSLATOR_INFO
  663.     short        i;
  664. #endif
  665.     Rect        theIconRect;
  666.     Str63           theStr;
  667.     
  668.     TextSize(10);
  669.     UpdateControls(window, window->visRgn);
  670.     MoveTo(kDummyHOffset, 16);
  671.     DrawString("\pSet Dummy Testing Information:");
  672.     
  673.     // Module Icon
  674.     SetRect(&theIconRect, kIconHOffset, 5, kIconHOffset + 32, 5 + 32);
  675.     if (gPluginInfo.icon && *gPluginInfo.icon)
  676.         PlotIconSuite(&theIconRect, atAbsoluteCenter, ttNone, gPluginInfo.icon);
  677.     
  678.     // Module Name
  679.     MoveTo(kButHOffset, 12);
  680.     DrawString("\pModule:");
  681.     if (gPluginInfo.desc != nil) {
  682.         CopyPP(*gPluginInfo.desc, theStr);
  683.         TextFace(bold);
  684.         MoveTo(kButHOffset, 24);
  685.         DrawString(theStr);
  686.         TextFace(normal);
  687.     }
  688.     
  689.     // API version
  690.     MoveTo(kButHOffset, 37);
  691.     DrawString("\pAPI Version: ");
  692.     ems_plugin_version(gModuleGlobalsH, &api_version);
  693.     NumToString(api_version, theStr);
  694.     DrawString(theStr);
  695.  
  696.     // Draw line
  697.     MoveTo(0, kHeaderOffset);
  698.     LineTo(600, kHeaderOffset);
  699.     
  700. #if EMS_HAS_TRANSLATOR_INFO
  701.     // Go through the translators in the module
  702.     for (i = 0; i < gPluginInfo.numTrans; i++) {
  703.         short               j, theType, v, err;
  704.         Rect            textBox;
  705.         unsigned long    mask;
  706.         emsTranslator    translInfo;
  707.         char            s[512];
  708.  
  709.         translInfo = gTranslBtns[i].trans;
  710.         v = i * kTransHeightOffset + kHeaderOffset + kTransTopOffset;
  711.         
  712.         /* Draw the icon */
  713.         SetRect(&theIconRect, kIconHOffset, v, kIconHOffset + 32, v + 32);
  714.         if (translInfo.icon == nil)        // substitute dummy icon if translator doesn't have one
  715.             err = GetIconSuite(&translInfo.icon, kDefTransIcon, svAllAvailableData);
  716.         if (translInfo.icon && *translInfo.icon)
  717.             PlotIconSuite(&theIconRect, atAbsoluteCenter, ttNone, translInfo.icon);
  718.  
  719.         MoveTo(kTextHOffset, v + 9);
  720.         sprintf(s, "Translator # %d: ", i + 1);
  721.         DrawString(CtoPstr(s));
  722.         if (translInfo.desc != nil) {
  723.             CopyPP(*translInfo.desc, theStr);
  724.             DrawString(theStr);
  725.         }
  726.  
  727.         /* The translator info details */
  728.         theType = (translInfo.type == EMST_NO_TYPE) ? 1 : (translInfo.type / 16)  + 1;
  729.         GetIndString(theStr, 2000, theType);
  730.         sprintf(s, "Type: %#s", theStr);
  731.         if (translInfo.flags & EMSF_REQUIRES_MIME)
  732.             strcat(s, ", wants MIME");
  733.         if (translInfo.flags & EMSF_GENERATES_MIME)
  734.             strcat(s, ", makes MIME");
  735.         if (translInfo.flags & EMSF_WHOLE_MESSAGE)
  736.             strcat(s, ", whole msg");
  737.         MoveTo(kTextHOffset, v + 23);
  738.         DrawString(CtoPstr(s));
  739.     
  740.         /* Some of the options */
  741.         MoveTo(kTextHOffset, v + 37);
  742.         DrawString("\pContext:");
  743.         s[0] = '\0';
  744.         for (j = 0; j < 8; j++) {
  745.             mask = (1L << j);
  746.             if ((translInfo.flags & mask) == mask) {
  747.                 if (strlen(s) != 0)
  748.                     strcat(s, ", ");
  749.                 GetIndString(theStr, 3000, j + 1);
  750.                 strcat(s, p2cstr(theStr));
  751.             }
  752.         }
  753.         SetRect(&textBox, kTextHOffset + 42, v + 27, kTextHOffset + 350, v + 56);
  754.         CtoPstr(s);
  755.         TETextBox(s + 1, s[0], &textBox, teFlushLeft);
  756.  
  757.         // Draw line
  758.         v = (i + 1) * kTransHeightOffset + kHeaderOffset;
  759.         MoveTo(kButHOffset, v);
  760.         LineTo(600, v);
  761.  
  762.         gTranslBtns[i].trans = translInfo;
  763.     }
  764. #endif
  765. }    
  766.  
  767.  
  768. /* ----------------------------------------------------------------------
  769.     Actually do a translation
  770.  */
  771. #if EMS_HAS_TRANSLATE_FILE
  772. void DoTranslation(emsTranslator *trans)
  773. {
  774.     short               theResult = EMSR_OK;
  775.        StandardFileReply    getReply, putReply;
  776.     emsMIMEtypeH        transMimeType = nil;
  777.     emsDataFile            dataFileIn, dataFileOut;
  778.     EMSProgressUPP        progressUPP = nil;
  779.  
  780.     StandardGetFile(nil, -1, nil, &getReply);
  781.     if (!getReply.sfGood)
  782.         return;
  783.     StandardPutFile("\pCreate the Output File", "\pOutputFile", &putReply);
  784.     if (!putReply.sfGood)
  785.         return;
  786.     DoUpdate(gDebugWindow);
  787.     
  788.     // Eudora will call ems_can_translate before calling ems_translate. Here we are
  789.     // assuming you can translate for the purposes of testing your code.
  790.      SetSize(dataFileIn);
  791.      dataFileIn.context = gContext;
  792.      dataFileIn.mimeInfo = gMimeTypeH;
  793.     dataFileIn.header = nil;
  794.      dataFileIn.file = getReply.sfFile;
  795.  
  796.     dataFileOut = dataFileIn;
  797.     dataFileOut.mimeInfo = nil;    //    HandToHand((Handle*) &dataFileOut.mimeInfo); // duplicate
  798.      dataFileOut.file = putReply.sfFile;
  799.  
  800. #if EMS_HAS_QUEUED_PROPERTIES
  801.     if (gContext == EMSF_Q4_TRANSMISSION) {    // pretend user is toggling icon on
  802.         long    selected = true;
  803.         
  804.         theResult = ems_queued_properties(gModuleGlobalsH, trans, &selected);
  805.         if (!selected) {
  806.             DoMessage(EMSR_DATA_UNCHANGED);
  807.             return;
  808.         }
  809.     }
  810. #endif
  811.     if (putReply.sfReplacing)
  812.         FSpDelete(&putReply.sfFile);
  813.     FSpCreate(&putReply.sfFile, 'ttxt', 'TEXT', smSystemScript);
  814.  
  815.     gProgressDlg = nil;
  816.     if (gContext == EMSF_ON_ARRIVAL || gContext == EMSF_Q4_TRANSMISSION) {
  817.         gProgressDlg = GetNewDialog(kProgressDlogID, nil, (WindowPtr) -1L);
  818.     }
  819.     theResult = ems_translate_file(gModuleGlobalsH, trans,
  820.                    &dataFileIn, gProgressUPP, &dataFileOut, &gResultStatus);
  821.     if (gProgressDlg != nil) {
  822.         DisposeDialog(gProgressDlg);
  823.     }
  824. #if EMS_HAS_QUEUED_PROPERTIES
  825.     if (gContext == EMSF_Q4_TRANSMISSION) {
  826.         if (trans->properties != nil) {
  827.             DisposeHandle((Handle) trans->properties);
  828.             trans->properties = nil;
  829.         }
  830.     }
  831. #endif
  832.     InvalRgn(gDebugWindow->visRgn);
  833.     DoUpdate(gDebugWindow);
  834.     DoMessage(theResult);    // Report how it all went
  835. }
  836. #endif
  837.  
  838.  
  839. /* ----------------------------------------------------------------------
  840.     Test if we can translate
  841.  */
  842. #if EMS_HAS_CAN_TRANSLATE
  843. void CanTranslation(emsTranslator *trans)
  844. {
  845.     long                theResult;
  846.        StandardFileReply    reply;
  847.        emsDataFile            dataFile;
  848.  
  849.     StandardGetFile(nil, -1, nil, &reply);
  850.     if (!reply.sfGood)
  851.         return;
  852.     
  853.      // Call the translator in the module
  854.      SetSize(dataFile);
  855.      dataFile.context = gContext;
  856.      dataFile.mimeInfo = gMimeTypeH;    // ?
  857.     dataFile.header = nil;            // ?
  858.      dataFile.file = reply.sfFile;
  859.     theResult = ems_can_translate(gModuleGlobalsH, trans, &dataFile, &gResultStatus);
  860.     InvalRgn(gDebugWindow->visRgn);
  861.     DoUpdate(gDebugWindow);        // redraw window after calling translator
  862.     DoMessage(theResult);        // Report how it all went
  863. }
  864. #endif
  865.  
  866.  
  867. /* ----------------------------------------------------------------------
  868.     Test if we can translate
  869.  */
  870. void NoTranslation(emsTranslator *trans)
  871. {
  872.     DoMessage(EMSR_CANT_TRANS);
  873. }
  874.  
  875. #pragma mark -
  876.  
  877. /*****************************************************************/
  878. /*  M I M E   D I A L O G
  879. /*****************************************************************/
  880.  
  881. #define kMimeStrBaseID        401
  882. #define kMimeDefStrBaseID    501
  883. #define kBaseMimeItem        20
  884. #define kTypeItem            22
  885. #define kSubtypeItem        23
  886. #define kBaseParamItem        24
  887.  
  888.  
  889. /* ----------------------------------------------------------------------
  890.     Handle Mime dialog
  891.  */
  892. void DoMimeDlog(void)
  893. {
  894.     DialogPtr        theDialog;
  895.     DialogRecord    dlgRec;
  896.     GrafPtr            savePort;
  897.     short            itemType, i;
  898.     Handle            itemH;
  899.     Rect            itemRect;
  900.     Boolean            done = false;
  901.     short            itemHit;
  902.     Str255            theStr;
  903.     
  904.     GetPort(&savePort);
  905.     UseResFile(gOurResRefNum);
  906.     theDialog = GetNewDialog(kMimeDlogID, &dlgRec, (WindowPtr) -1L);
  907.     if (theDialog == nil)
  908.         return;
  909.  
  910.     for (i = 0; i < 14; i++) {
  911.         GetStringHdl(kMimeStrBaseID + i, theStr);
  912.         GetDialogItem(theDialog, kBaseMimeItem + i, &itemType, &itemH, &itemRect);
  913.         if (itemH != nil)
  914.             SetDialogItemText(itemH, theStr);
  915.     }
  916.     SelectDialogItemText(theDialog, kBaseMimeItem, 0, 32767);
  917.     SetPort(theDialog);
  918.     SetWindowFont(theDialog, applFont, 9, normal);
  919.     SetDialogDefaultItem(theDialog, kOK);
  920.     SetDialogCancelItem(theDialog, kCancel);
  921.     ShowWindow(theDialog);
  922.     
  923.     while (!done) {
  924.         ModalDialog(nil, &itemHit);
  925.         switch (itemHit) {
  926.             case kOK:
  927.                 done = true;
  928.                 SaveMimeSettingsToFile(theDialog);
  929.                 FreeMimeType(gMimeTypeH);
  930.                 BuildNewMimeData();
  931.                 break;
  932.             case kCancel:
  933.                 done = true;
  934.                 break;
  935.             case kFactorySettings:
  936.                 RestoreMimeDefaults(theDialog);
  937.                 break;
  938.             default:
  939.                 break;
  940.         }
  941.     }
  942.     CloseDialog(theDialog);
  943.     SetPort(savePort);
  944. }
  945.  
  946.  
  947. /* ----------------------------------------------------------------------
  948.     Restore default mime values
  949.  */
  950. void RestoreMimeDefaults(DialogPtr theDialog)
  951. {
  952.     short        itemType, i;
  953.     Handle        itemH;
  954.     Rect        itemRect;
  955.     Str255        theStr;
  956.  
  957.     for (i = 0; i < 4; i++) {
  958.         GetStringHdl(kMimeDefStrBaseID + i, theStr);
  959.         GetDialogItem(theDialog, kBaseMimeItem + i, &itemType, &itemH, &itemRect);
  960.         SetDialogItemText(itemH, theStr);
  961.     }
  962.     for (i = 4; i < 14; i++) {
  963.         GetDialogItem(theDialog, kBaseMimeItem + i, &itemType, &itemH, &itemRect);
  964.         SetDialogItemText(itemH, "\p");
  965.     }
  966. }
  967.  
  968.  
  969. /* ----------------------------------------------------------------------
  970.     Save dialog contents
  971.  */
  972. void SaveMimeSettingsToFile(DialogPtr theDialog)
  973. {
  974.     short            itemType, i;
  975.     Handle            itemH;
  976.     Rect            itemRect;
  977.     Str255            textStr;
  978.     StringHandle    strH;
  979.  
  980.     UseResFile(gOurResRefNum);
  981.     for (i = 0; i < 14; i++) {
  982.         GetDialogItem(theDialog, kBaseMimeItem + i, &itemType, &itemH, &itemRect);
  983.         GetDialogItemText(itemH, textStr);
  984.         
  985.         strH = GetString(kMimeStrBaseID + i);
  986.         if (strH != nil) {
  987.             SetString(strH, textStr);
  988.             ChangedResource((Handle) strH);
  989.             WriteResource((Handle) strH);
  990.             ReleaseResource((Handle) strH);
  991.         }
  992.     }
  993.     UpdateResFile(gOurResRefNum);
  994. }
  995.  
  996.  
  997. /* ----------------------------------------------------------------------
  998.     Setup mime dialog
  999.  */
  1000. void BuildNewMimeData(void)
  1001. {
  1002.     short            i;
  1003.     Str255            str1, str2;
  1004.     
  1005.     UseResFile(gOurResRefNum);
  1006.     GetStringHdl(kMimeStrBaseID, str1);
  1007.     GetStringHdl(kMimeStrBaseID + 1, str2);
  1008.     gMimeTypeH = MakeMimeType(str1, str2, nil);
  1009.     if (gMimeTypeH != nil) {    /* Loop for six parameters in dialog. */
  1010.         for (i = 0; i < 6; i++) {
  1011.             GetStringHdl(kMimeStrBaseID + 2 + (i * 2), str1);
  1012.             GetStringHdl(kMimeStrBaseID + 3 + (i * 2), str2);
  1013.             if ((str1[0] != 0) || (str2[0] != 0))
  1014.                 AddMimeParameter(gMimeTypeH, str1, str2);                
  1015.         }
  1016.     }
  1017. }
  1018.  
  1019. #pragma mark -
  1020.  
  1021. /*****************************************************************/
  1022. /*  A D D R E S S   D I A L O G
  1023. /*****************************************************************/
  1024.  
  1025. #define kAddressStrBaseID    701
  1026. #define KAddDefStrBaseID    801
  1027. #define kBaseAddressItem    14
  1028.  
  1029. /* ----------------------------------------------------------------------
  1030.     Handle address dialog
  1031.  */
  1032. void DoAddressDlog(void)
  1033. {
  1034.     DialogPtr        theDialog;
  1035.     DialogRecord    dlgRec;
  1036.     GrafPtr            savePort;
  1037.     Boolean            done = false;
  1038.     short            itemHit;
  1039.     
  1040.     GetPort(&savePort);
  1041.     UseResFile(gOurResRefNum);
  1042.     theDialog = GetNewDialog(kAddressDlogID, &dlgRec, (WindowPtr) -1L);
  1043.     if (theDialog != nil) {
  1044.         SetPort(theDialog);
  1045.         SetWindowFont(theDialog, applFont, 9, normal);
  1046.         SetDialogDefaultItem(theDialog, kOK);
  1047.         SetDialogCancelItem(theDialog, kCancel);
  1048.         SetupAddressDialog(theDialog);
  1049.         ShowWindow(theDialog);
  1050.         while (!done) {
  1051.             ModalDialog(nil, &itemHit);
  1052.             switch (itemHit) {
  1053.                 case kOK:
  1054.                     SaveAddressSettingsToFile(theDialog);
  1055.                     GetAddressChanges(theDialog);
  1056.                 case kCancel:
  1057.                     done = true;
  1058.                     break;
  1059.                 case kFactorySettings:
  1060.                     RestoreAddressDefaults(theDialog);
  1061.                     break;
  1062.             }
  1063.         }
  1064.         CloseDialog(theDialog);
  1065.         SetPort(savePort);
  1066.     }
  1067. }
  1068.  
  1069.  
  1070. /* ----------------------------------------------------------------------
  1071.     Load dialog settings from resources
  1072.  */
  1073. void RestoreAddressDefaults(DialogPtr theDialog)
  1074. {
  1075.     short        itemType, i;
  1076.     Handle        itemH;
  1077.     Rect        itemRect;
  1078.     Str255        theStr;
  1079.  
  1080.     for (i = 0; i < 3; i++) {
  1081.         GetStringHdl(KAddDefStrBaseID + i, theStr);
  1082.         GetDialogItem(theDialog, kBaseAddressItem + i, &itemType, &itemH, &itemRect);
  1083.         SetDialogItemText(itemH, theStr);
  1084.     }
  1085.     for (i = 3; i < 9; i++) {
  1086.         GetDialogItem(theDialog, kBaseAddressItem + i, &itemType, &itemH, &itemRect);
  1087.         SetDialogItemText(itemH, "\p");
  1088.     }
  1089. }
  1090.  
  1091.  
  1092. /* ----------------------------------------------------------------------
  1093.     Save dialog settings to resources
  1094.  */
  1095. void SaveAddressSettingsToFile(DialogPtr theDialog)
  1096. {
  1097.     short            itemType, i;
  1098.     Handle            itemH;
  1099.     Rect            itemRect;
  1100.     Str255            textStr;
  1101.     StringHandle    strH;
  1102.  
  1103.     UseResFile(gOurResRefNum);
  1104.     for (i = 0; i < 9; i++) {
  1105.         GetDialogItem(theDialog, kBaseAddressItem + i, &itemType, &itemH, &itemRect);
  1106.         GetDialogItemText(itemH, textStr);
  1107.         
  1108.         strH = GetString(kAddressStrBaseID + i);
  1109.         if (strH != nil) {
  1110.             SetString(strH, textStr);
  1111.             ChangedResource((Handle) strH);
  1112.             WriteResource((Handle) strH);
  1113.             ReleaseResource((Handle) strH);
  1114.         }
  1115.     }
  1116.     UpdateResFile(gOurResRefNum);
  1117. }
  1118.  
  1119.  
  1120. /* ----------------------------------------------------------------------
  1121.     Initialize dialog settings from resources
  1122.  */
  1123. void SetupAddressDialog(DialogPtr theDialog)
  1124. {
  1125.     short            itemType, i;
  1126.     Handle            itemH;
  1127.     Rect            itemRect;
  1128.     Str255            theStr;
  1129.  
  1130.     for (i = 0; i < 9; i++) {
  1131.         GetStringHdl(kAddressStrBaseID + i, theStr);
  1132.         GetDialogItem(theDialog, kBaseAddressItem + i, &itemType, &itemH, &itemRect);
  1133.         SetDialogItemText(itemH, theStr);
  1134.     }
  1135.     SelectDialogItemText(theDialog, kBaseAddressItem, 0, 32767);
  1136. }
  1137.  
  1138.  
  1139. /* ----------------------------------------------------------------------
  1140.     Copy dialog settings to addresses global
  1141.  */
  1142. void GetAddressChanges(DialogPtr theDialog)
  1143. {
  1144.     short            itemType, i;
  1145.     Handle            itemH;
  1146.     Rect            itemRect;
  1147.     StringHandle    strH;
  1148.     Str255            textStr;
  1149.     
  1150.     for (i = 0; i < 9; i++) {
  1151.         GetDialogItem(theDialog, kBaseAddressItem + i, &itemType, &itemH, &itemRect);
  1152.         GetDialogItemText(itemH, textStr);
  1153.         strH = (*gAddressesH)[i];
  1154.         if (strH == nil)
  1155.             strH = (StringHandle) NewHandle(0);
  1156.         SetString(strH, textStr);
  1157.         (*gAddressesH)[i] = strH;
  1158.     }    
  1159. }
  1160.  
  1161.  
  1162. /* ----------------------------------------------------------------------
  1163.     Create addresses global from resources
  1164.  */
  1165. void InitAddressData(void)
  1166. {
  1167.     short            i;
  1168.     StringHandle    resH;
  1169.  
  1170.     UseResFile(gOurResRefNum);
  1171.     gAddressesH = (StringHandle**) NewHandleClear(10 * sizeof(StringHandle));
  1172.     for (i = 0; i < 9; i++) {
  1173.         resH = GetString(kAddressStrBaseID + i);
  1174.         if (resH != nil) {
  1175.             DetachResource((Handle) resH);
  1176.             (*gAddressesH)[i] = resH;
  1177.         }
  1178.     }
  1179.     (*gAddressesH)[9] = nil;    // last StringHandle is nil
  1180. }
  1181.  
  1182.  
  1183. #pragma mark -
  1184. /*****************************************************************/
  1185. /*  C O N T E X T
  1186. /*****************************************************************/
  1187.  
  1188. short ContextToMenuItem(long context)
  1189. {
  1190.     short        item;
  1191.     
  1192.     switch (context & 0x000FFFF) {
  1193.         case EMSF_ON_ARRIVAL:        item = 1;        break;
  1194.         case EMSF_ON_DISPLAY:        item = 2;        break;
  1195.         case EMSF_ON_REQUEST:        item = 3;        break;
  1196.         case EMSF_Q4_TRANSMISSION:    item = 4;        break;
  1197.     }
  1198.     return item;
  1199. }
  1200.  
  1201. long MenuItemToContext(short item)
  1202. {
  1203.     long        context;
  1204.     
  1205.     switch (item) {
  1206.         case 1:        context = EMSF_ON_ARRIVAL;        break;
  1207.         case 2:        context = EMSF_ON_DISPLAY;        break;
  1208.         case 3:        context = EMSF_ON_REQUEST;        break;
  1209.         case 4:        context = EMSF_Q4_TRANSMISSION;    break;
  1210.     }
  1211.     return context;
  1212. }
  1213.  
  1214. #pragma mark -
  1215.  
  1216. /*****************************************************************/
  1217. /*  S U P P O R T  R O U T I N E S
  1218. /*****************************************************************/
  1219.  
  1220. /* ----------------------------------------------------------------------
  1221.     Display message dialog
  1222.  */
  1223. void DoMessage(long status)
  1224. {
  1225.     Str255        theStr;
  1226.     Str31        numStr;
  1227.     
  1228.     CopyPP("\pResult: ", theStr);
  1229.     if ((status >= EMSR_OK) && (status <= EMSR_DATA_UNCHANGED)) {
  1230.         CatPP(translatorErrors[status], theStr);
  1231.         if (gResultStatus.desc != nil) {
  1232.             CatPP(*gResultStatus.desc, theStr);
  1233.             DisposeHandle((Handle) gResultStatus.desc);
  1234.             gResultStatus.desc = nil;
  1235.         }
  1236.     }
  1237.     else
  1238.         CatPP("\pbad result", theStr);
  1239.     CatPP("\p\rCode: ", theStr);
  1240.     NumToString(gResultStatus.code, numStr);
  1241.     CatPP(numStr, theStr);
  1242.     ParamText(theStr, "\p", "\p", "\p");
  1243.     Alert(kNoteALRTid, nil);
  1244. }
  1245.  
  1246.  
  1247. /* ----------------------------------------------------------------------
  1248.     Display error dialog if error
  1249.  */
  1250. void DoError(long error, Str63 message)
  1251. {
  1252.     Str255        errStr;
  1253.     
  1254.     if (error != EMSR_OK && error != EMSR_DATA_UNCHANGED) {    // Report how it all went
  1255.         CopyPP(message, errStr);
  1256.         CatPP("\p: ", errStr);
  1257.         if ((error >= EMSR_OK) && (error <= EMSR_ABORTED))
  1258.             CatPP(translatorErrors[error], errStr);
  1259.         else
  1260.             CatPP("\pbad result", errStr);
  1261.         ParamText(errStr, "\p", "\p", "\p");
  1262.         Alert(kErrorALRTid, nil);
  1263.         ExitToShell();
  1264.     }
  1265. }
  1266.  
  1267.  
  1268. /* ----------------------------------------------------------------------
  1269.     Copy STR resource to Str255
  1270.  */
  1271. void GetStringHdl(short id, Str255 theStr)
  1272. {
  1273.     StringHandle    strH;
  1274.     
  1275.     strH = GetString(id);
  1276.     if (strH != nil) {
  1277.         CopyPP(*strH, theStr);
  1278.         ReleaseResource((Handle) strH);
  1279.     }
  1280.     else
  1281.         theStr[0] = '\0';
  1282. }
  1283.  
  1284.  
  1285. /* ----------------------------------------------------------------------
  1286.     Set dialog's font
  1287.  */
  1288. void SetWindowFont(DialogPtr theDialog, short fontNum, short fontSize, Style fontStyle)
  1289. {
  1290.     FontInfo    fInfo;
  1291.     GrafPtr        savePort;
  1292.     TEHandle    theTE;
  1293.     
  1294.     theTE = ((DialogPeek) theDialog)->textH;
  1295.     if (theTE != nil) {
  1296.         GetPort(&savePort);
  1297.         SetPort(theDialog);
  1298.         
  1299.         TextFont(fontNum);
  1300.         TextSize(fontSize);
  1301.         TextFace(fontStyle);
  1302.            
  1303.         (**theTE).txFont = fontNum;
  1304.         (**theTE).txFace = fontStyle;
  1305.         (**theTE).txSize = fontSize;
  1306.            GetFontInfo(&fInfo);
  1307.         (**theTE).fontAscent = fInfo.ascent;
  1308.         (**theTE).lineHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
  1309.  
  1310.         SetPort(savePort);
  1311.     }
  1312. }
  1313.  
  1314.  
  1315. /* ----------------------------------------------------------------------
  1316.     Simulate Eudora's progress routine
  1317.  */
  1318. #define kPercentItem        2
  1319. #define kMessageItem        3
  1320.  
  1321. short ProgressProc(emsProgressData *prog)
  1322. {
  1323.     GrafPtr            savePort;
  1324.     WindowPtr        theWindow;
  1325.     short            itemType, part, result = 0;
  1326.     Str15            pctStr;
  1327.     Handle            itemH;
  1328.     ControlHandle    hCtl;
  1329.     Point            mousePt;
  1330.     Rect            itemRect;
  1331.  
  1332.     /* The translator should call this function periodically with emsProgressData.value
  1333.      * between 0 and 100 (percent). The translator should check the return value.
  1334.      *         false - continue translation
  1335.      *        true - abort translation
  1336.      *
  1337.      * If you are supplying your own progress function, call this with -1
  1338.      * to check for abort.
  1339.      */
  1340.     if (gProgressDlg == nil)
  1341.         return result;
  1342.     if (prog->value == 0) {
  1343.         ShowWindow(gProgressDlg);
  1344.         return result;
  1345.     }
  1346.     if (prog->value == 100) {
  1347.         HideWindow(gProgressDlg);
  1348.         return result;
  1349.     }
  1350.     GetPort(&savePort);
  1351.     SetPort(gProgressDlg);
  1352.     if (!EmptyRgn(((DialogPeek) gProgressDlg)->window.updateRgn)) {
  1353.         BeginUpdate(gProgressDlg);
  1354.         UpdateDialog(gProgressDlg, gProgressDlg->visRgn);
  1355.         EndUpdate(gProgressDlg);
  1356.     }
  1357.     if (prog->value >= 0) {
  1358.         NumToString(prog->value, pctStr);
  1359.         GetDialogItem(gProgressDlg, kPercentItem, &itemType, &itemH, &itemRect);
  1360.         SetDialogItemText(itemH, pctStr);
  1361.     }
  1362.     if (prog->message != nil) {
  1363.         GetDialogItem(gProgressDlg, kMessageItem, &itemType, &itemH, &itemRect);
  1364.         SetDialogItemText(itemH, prog->message);
  1365.     }
  1366.     if (Button()) {
  1367.         GetMouse(&mousePt);
  1368.         LocalToGlobal(&mousePt);
  1369.         part = FindWindow(mousePt, &theWindow);
  1370.         if (part == inContent && theWindow == gProgressDlg) {
  1371.             GlobalToLocal(&mousePt);
  1372.             part = FindControl(mousePt, gProgressDlg, &hCtl);
  1373.             if (part == kControlButtonPart) {    // we only have one button...
  1374.                 part = TrackControl(hCtl, mousePt, nil);
  1375.                 if (part == kControlButtonPart)
  1376.                     result = 1;        // user cancelled
  1377.             }
  1378.         }
  1379.     }
  1380.     SystemTask();
  1381.     SetPort(savePort);
  1382.     return result;
  1383. }
  1384.